import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.rsbot.script.methods.Game;
import org.rsbot.script.methods.Walking;
import org.rsbot.script.wrappers.RSTile;

class MapExplorer$AStar
{
  private Walking walking;
  private Game game;
  private int[][] flags;
  private int off_x;
  private int off_y;

  public void init(Game paramGame, Walking paramWalking)
  {
    this.game = paramGame;
    this.walking = paramWalking;
  }

  public RSTile[] findPath(RSTile paramRSTile1, RSTile paramRSTile2) {
    int i = this.game.getBaseX(); int j = this.game.getBaseY();
    int k = paramRSTile1.getX() - i; int m = paramRSTile1.getY() - j;
    int n = paramRSTile2.getX() - i; int i1 = paramRSTile2.getY() - j;

    this.flags = this.walking.getCollisionFlags(this.game.getPlane());
    RSTile localRSTile = this.walking.getCollisionOffset(this.game.getPlane());
    this.off_x = localRSTile.getX();
    this.off_y = localRSTile.getY();

    if ((this.flags == null) || (k < 0) || (m < 0) || (k >= this.flags.length) || (m >= this.flags.length) || (n < 0) || (i1 < 0) || (n >= this.flags.length) || (i1 >= this.flags.length))
    {
      return null;
    }

    HashSet localHashSet1 = new HashSet();
    HashSet localHashSet2 = new HashSet();
    MapExplorer.AStar.Node localNode1 = new MapExplorer.AStar.Node(k, m);
    MapExplorer.AStar.Node localNode2 = new MapExplorer.AStar.Node(n, i1);

    localNode1.f = heuristic(localNode1, localNode2);
    localHashSet1.add(localNode1);

    while (!localHashSet1.isEmpty()) {
      localNode1 = lowest_f(localHashSet1);
      if (localNode1.equals(localNode2))
      {
        return path(localNode1, i, j);
      }
      localHashSet1.remove(localNode1);
      localHashSet2.add(localNode1);
      for (MapExplorer.AStar.Node localNode3 : successors(localNode1)) {
        if (!localHashSet2.contains(localNode3)) {
          double d = localNode1.g + dist(localNode1, localNode3);
          int i2 = 0;
          if (!localHashSet1.contains(localNode3)) {
            localHashSet1.add(localNode3);
            i2 = 1;
          } else if (d < localNode3.g) {
            i2 = 1;
          }
          if (i2 != 0) {
            localNode3.prev = localNode1;
            localNode3.g = d;
            localNode3.f = (d + heuristic(localNode3, localNode2));
          }
        }
      }

    }

    return null;
  }

  private double heuristic(MapExplorer.AStar.Node paramNode1, MapExplorer.AStar.Node paramNode2) {
    double d1 = paramNode1.x - paramNode2.x;
    double d2 = paramNode1.y - paramNode2.y;
    if (d1 < 0.0D) d1 = -d1;
    if (d2 < 0.0D) d2 = -d2;
    return d1 < d2 ? d2 : d1;
  }

  private double dist(MapExplorer.AStar.Node paramNode1, MapExplorer.AStar.Node paramNode2)
  {
    if ((paramNode1.x != paramNode2.x) && (paramNode1.y != paramNode2.y)) {
      return 1.41421356D;
    }
    return 1.0D;
  }

  private MapExplorer.AStar.Node lowest_f(Set<MapExplorer.AStar.Node> paramSet)
  {
    Object localObject = null;
    for (MapExplorer.AStar.Node localNode : paramSet) {
      if ((localObject == null) || (localNode.f < localObject.f)) {
        localObject = localNode;
      }
    }
    return localObject;
  }

  private RSTile[] path(MapExplorer.AStar.Node paramNode, int paramInt1, int paramInt2) {
    LinkedList localLinkedList = new LinkedList();
    MapExplorer.AStar.Node localNode = paramNode;
    while (localNode != null) {
      localLinkedList.addFirst(localNode.toRSTile(paramInt1, paramInt2));
      localNode = localNode.prev;
    }
    return (RSTile[])localLinkedList.toArray(new RSTile[localLinkedList.size()]);
  }

  private List<MapExplorer.AStar.Node> successors(MapExplorer.AStar.Node paramNode) {
    LinkedList localLinkedList = new LinkedList();
    int i = paramNode.x; int j = paramNode.y;
    int k = i - this.off_x; int m = j - this.off_y;
    int n = this.flags[k][m];
    if ((m > 0) && ((n & 0x20) == 0) && ((this.flags[k][(m - 1)] & 0x100) == 0)) {
      localLinkedList.add(new MapExplorer.AStar.Node(i, j - 1));
    }
    if ((k > 0) && ((n & 0x80) == 0) && ((this.flags[(k - 1)][m] & 0x100) == 0)) {
      localLinkedList.add(new MapExplorer.AStar.Node(i - 1, j));
    }
    if ((m < 103) && ((n & 0x2) == 0) && ((this.flags[k][(m + 1)] & 0x100) == 0)) {
      localLinkedList.add(new MapExplorer.AStar.Node(i, j + 1));
    }
    if ((k < 103) && ((n & 0x8) == 0) && ((this.flags[(k + 1)][m] & 0x100) == 0)) {
      localLinkedList.add(new MapExplorer.AStar.Node(i + 1, j));
    }
    if ((k > 0) && (m > 0) && ((n & 0xE0) == 0) && ((this.flags[(k - 1)][(m - 1)] & 0x100) == 0) && ((this.flags[k][(m - 1)] & 0x180) == 0) && ((this.flags[(k - 1)][m] & 0x120) == 0))
    {
      localLinkedList.add(new MapExplorer.AStar.Node(i - 1, j - 1));
    }
    if ((k > 0) && (m < 103) && ((n & 0x83) == 0) && ((this.flags[(k - 1)][(m + 1)] & 0x100) == 0) && ((this.flags[k][(m + 1)] & 0x180) == 0) && ((this.flags[(k - 1)][m] & 0x102) == 0))
    {
      localLinkedList.add(new MapExplorer.AStar.Node(i - 1, j + 1));
    }
    if ((k < 103) && (m > 0) && ((n & 0x38) == 0) && ((this.flags[(k + 1)][(m - 1)] & 0x100) == 0) && ((this.flags[k][(m - 1)] & 0x108) == 0) && ((this.flags[(k + 1)][m] & 0x120) == 0))
    {
      localLinkedList.add(new MapExplorer.AStar.Node(i + 1, j - 1));
    }
    if ((k > 0) && (m < 103) && ((n & 0xE) == 0) && ((this.flags[(k + 1)][(m + 1)] & 0x100) == 0) && ((this.flags[k][(m + 1)] & 0x108) == 0) && ((this.flags[(k + 1)][m] & 0x102) == 0))
    {
      localLinkedList.add(new MapExplorer.AStar.Node(i + 1, j + 1));
    }
    return localLinkedList;
  }
}